package com.acme.bankapp.domain.bank;

import com.acme.bankapp.domain.exceptions.OverDraftLimitExceededException;

/**
 * Created by zurdan on 14.11.14.
 * E-mail: Zurdanium@gmail.com
 */
public class CheckingAccount extends AbstractAccount {

    private double overdraft;
    private final double maxOverdraft;

    public CheckingAccount(final double amount, final double overdraft) {
        super(amount);
        if (overdraft < 0) {
            throw new IllegalArgumentException("Negative overdraft");
        }
        this.overdraft = overdraft;
        this.maxOverdraft = overdraft;
    }

    @Override
    protected void doDeposit(final double amount) {
        if(overdraft < maxOverdraft) {
            overdraft += amount;
            if(overdraft > maxOverdraft) {
                setBalance(getBalance() + overdraft - maxOverdraft);
                overdraft = maxOverdraft;
            }
        } else {
            setBalance(getBalance() + amount);
        }
    }

    @Override
    protected void doWithdraw(final double amount) throws OverDraftLimitExceededException {
        if (!isMoneyEnough(amount)) {
            throw new OverDraftLimitExceededException(maximumAmountToWithdraw());
        }
        if (getBalance() >= amount) {
            setBalance(getBalance() - amount);
        } else {
            overdraft -= amount - getBalance();
            setBalance(0);
        }
    }


    public double maximumAmountToWithdraw() {
        return getBalance() + overdraft;
    }

    @Override
    public String toString() {
        return new StringBuilder("CheckingAccount{")
                .append("balance=")
                .append(decimalValue())
                .append(", overdraft=")
                .append(overdraft)
                .append(", maxOverdraft=")
                .append(maxOverdraft)
                .append('}')
                .toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CheckingAccount)) return false;
        if (!super.equals(o)) return false;

        CheckingAccount that = (CheckingAccount) o;

        if (Double.compare(that.maxOverdraft, maxOverdraft) != 0) return false;
        if (Double.compare(that.overdraft, overdraft) != 0) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        long temp;
        temp = Double.doubleToLongBits(overdraft);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(maxOverdraft);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
}
